
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * tick internal variable and functions used by low/high res code
 */
#ifndef KERNEL_TIME_TICK_INTERNAL_H
#define KERNEL_TIME_TICK_INTERNAL_H

#include <seminix/cache.h>
#include <seminix/percpu.h>
#include <seminix/thread_info.h>
#include <seminix/hrtimer.h>
#include <devices/clockchips.h>

enum tick_device_mode {
    TICKDEV_MODE_PERIODIC,
    TICKDEV_MODE_ONESHOT,
};

struct tick_device {
    struct clock_event_device *evtdev;
    enum tick_device_mode mode;
};

DECLARE_PER_CPU(struct tick_device, tick_cpu_device);

#define TICK_DO_TIMER_NONE	-1
#define TICK_DO_TIMER_BOOT	-2

extern int tick_do_timer_cpu __read_mostly;

extern void tick_check_new_device(struct clock_event_device *dev);

extern int tick_program_event(ktime_t expires, int force);
extern void tick_setup_oneshot(struct clock_event_device *newdev,
            void (*handler)(struct clock_event_device *),
            ktime_t next_event);
extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
extern int tick_oneshot_init_highres(void);
extern int tick_oneshot_mode_active(void);


/*
 * tick internal variable and functions used by low/high res code
 */

static inline enum clock_event_state clockevent_get_state(struct clock_event_device *dev)
{
    return dev->state_use_accessors;
}

static inline void clockevent_set_state(struct clock_event_device *dev,
                    enum clock_event_state state)
{
    dev->state_use_accessors = state;
}

extern void clockevents_switch_state(struct clock_event_device *dev,
                     enum clock_event_state state);
extern void clockevents_shutdown(struct clock_event_device *dev);
extern int clockevents_tick_resume(struct clock_event_device *dev);

extern int clockevents_program_event(struct clock_event_device *dev,
                     ktime_t expires, bool force);

extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);

extern void clockevents_handle_noop(struct clock_event_device *dev);

extern void clockevents_exchange_device(struct clock_event_device *old,
                    struct clock_event_device *new);

#endif /* !KERNEL_TIME_TICK_INTERNAL_H */
